package xyz.scootaloo.kami.server.service

import io.vertx.core.CompositeFuture
import io.vertx.core.Future
import xyz.scootaloo.kami.server.model.ActualUploadFileInfo
import xyz.scootaloo.kami.server.model.EFile
import xyz.scootaloo.kami.server.model.SingleUploadFileInfo
import xyz.scootaloo.kami.server.standard.InternalApi
import xyz.scootaloo.kami.server.standard.NaughtyStep
import xyz.scootaloo.kami.server.service.impl.InternalFileResolverImpl

/**
 * 提供系统内大部分对文件系统操作的功能接口
 *
 * @author flutterdash@qq.com
 * @since 2022/2/12 16:58
 */
interface FileResolver {

    companion object {
        operator fun invoke(): FileResolver {
            return InternalFileResolverImpl
        }
    }

    fun home(): String
    fun assets(): String
    fun tmp(): String

    // 不会对文件系统结构修改的接口, 仅对文件系统的信息进行查看

    @InternalApi fun realPathString(relativePath: String, vararg subPaths: String): String
    fun splitFilepath(filepath: String): Pair<String, String>
    fun humanReadableSize(size: Long): String
    fun pathNormalize(anyPath: String): String
    fun buildFilepath(basePath: String, vararg appends: String): String
    fun resolveFile(relativePath: String): EFile
    fun listDirContents(relativeDirPath: String, fileFilter: SubFileFilter): List<EFile>
    fun isDirectory(relativePath: String): Boolean
    fun isExists(relativeFilepath: String): Boolean
    @NaughtyStep fun calculateDirStorageSpace(relativeDirPath: String, cache: Map<String, Long>): Long

    // 会对文件系统的结构产生修改的接口

    /**
     * 当一个文件上传完成时(临时文件的每一个部分都已经填充完成),
     * 需要把[tmpFilename]的文件名修改为实际上传的文件名, 也就是去掉.tmp后缀
     */
    fun finishUploadTask(relativeDirPath: String, tmpFilename: String): Future<String>
    fun deleteFiles(relativeDirPath: String, files: Collection<String>): CompositeFuture
    fun deleteFile(relativeDirPath: String, filename: String): Future<Void>
    fun createFile(relativeDirPath: String, filename: String): Future<Unit>
    fun createDir(relativeDirPath: String, dirName: String): Future<Unit>
    fun rename(relativeDirPath: String, oldName: String, newName: String): Future<Unit>
    fun move(relativeDirPath: String, filename: String, relativeDestPath: String): Future<Void>
    suspend fun createTmpUploadFiles(relativeDirPath: String, files: List<SingleUploadFileInfo>): List<ActualUploadFileInfo>

    /**
     * 文件过滤器, 用于过滤一个文件夹的一些文件
     *
     * 当希望某些文件不出现在结果中时, 应该实现[filter]方法,
     * 并当这个文件名传入方法时, 返回false
     */
    fun interface SubFileFilter {
        /**
         * @param subFilename 文件名
         */
        fun filter(subFilename: String): Boolean
    }
}